package calcsdk.test;

import calcsdk.Calcsdk;
import calcsdk.nw.Util;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author 3bl3gamer
 */
public class FindDistExt {
	
	private Calcsdk core=null;
	private float mas[][]=null;
	private float distBuf[][]=null;
	private int idBuf[][]=null;
	
	
	public FindDistExt(float mas[][], Calcsdk core) {
		this.core=core;
		this.mas=mas;
		distBuf=new float[mas.length][];
		idBuf=new int[mas.length][];
		
		for (int i=0;i<mas.length;i++) find(i);
		
		if (core==null || core.DEBUG) {
			System.out.println(Util.arrayToString(distBuf));
			System.out.println(Util.arrayToString(idBuf));
		}
	}
	
	private void find(int source) {
        int n = mas.length;
		float dist[]=new float[n];
		int id[]=new int[n];
		
        for (int i = 0; i < n; i++) {
            dist[i] = Float.POSITIVE_INFINITY;
        }
        dist[source] = 0;
		id[source]=source;
        int mode[] = new int[n];//0 - processing, 1 - fixed
		
        while (true) {
            int min = -1;
            float minDist = Float.POSITIVE_INFINITY;
            for (int i = 0; i < n; i++) {
                if (mode[i] == 0 && dist[i] < minDist) {
                    minDist = dist[i];
                    min = i;
                }
            }
            if (min == -1) {
                break;
            }

            for (int i = 0; i < n; i++) {
                if (mas[min][i] != mas[min][i]) {
                    continue;
                }
                float tDist = dist[min] + mas[min][i];
                if (dist[i] > tDist) {
                    dist[i] = tDist;
					id[i]=min;
                }// else {
				//	if (dist[i] == tDist) System.out.println("+1");
				//}
            }
            mode[min] = 1;
//            if (core==null || core.DEBUG) {
//				Util.arrayPrint(dist);
//				Util.arrayPrint(id);
//			}
        }

        distBuf[source]=dist;
		idBuf[source]=id;
    }
	
	
	public float[][] getDist(boolean writeNans) {
		float[][] ret=Util.arrayCopy(distBuf);
		if (writeNans)
			for (int i=0;i<ret.length;i++) ret[i][i]=Float.NaN;
		return ret;
	}
	
	public int[] extractPath(int[] inPath, int addVal, int startPatch, int endPatch) {
		int t[];
		if (startPatch!=-1) {
			int pos=Util.arraySearch(inPath, startPatch);
			t=new int[inPath.length];
			for (int i=0;i<inPath.length-1;i++)
				t[i]=inPath[(pos+i)%(inPath.length-1)];
			t[inPath.length-1]=startPatch;
			inPath=t;
		}
		
		List<Integer> path=new ArrayList<Integer>();
		path.add(inPath[0]+addVal);
		for (int i=0;i<inPath.length-1;i++) {
			int from=inPath[i];
			int to=inPath[i+1];
			if (i!=0 || endPatch==-1) 
			while (idBuf[to][from]!=to) {
				from=idBuf[to][from];
				path.add(from+addVal);
			}
			path.add(to+addVal);
		}
		return Util.buildIntArray(path);
	}
}
